/*
 * DebugLogger.java
 *
 * Created on 25 mai 2006, 22:54
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package courselog;

import ewe.fx.Dimension;
import ewe.io.FileWriter;
import ewe.io.IOException;
import ewe.sys.Device;
import ewe.sys.Time;
import ewe.sys.Vm;
import ewe.sys.mThread;
import ewe.ui.Control;
import ewe.ui.ControlConstants;
import ewe.ui.Gui;
import ewe.ui.MessageBox;
import ewe.ui.mTextPad;

/**
 * Traces debugging in a TextArea and in System.out under Windows.
 * @author rigal
 */
public class DebugLogger {
    
    /** Configure the debug logger with a control. */
    public final boolean ISCONTROLENABLED=false;
    
    /** Configure the debug logger with a file. */
    public final boolean ISFILEENABLED=false;
    
    /**
     * Dump file name.
     */
    public final String LOGFILE="logfile.txt";
    
    /**
     * Textpad where items are displayed.
     */
    protected mTextPad logPad;
    
    /**
     * scrolling control where items are displayed.
     */
    protected Control logControl;
    
    /**
     * logContent.
     */
    protected String stLogContent;
    
    /**
     * Freezed state.
     */
    protected boolean isFreezed=false;
    
    /**
     * Output log file.
     */
    protected FileWriter fLog;
    
    /**
     * New instance of debuglogger. Provides the textpad.
     */
    public DebugLogger() {
        if(ISFILEENABLED) {
            try {
                fLog=new FileWriter(new ewe.io.File(LOGFILE));
                fLog.println(new Time().toString());
            } catch (SecurityException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        if(ISCONTROLENABLED) {
            logPad= new mTextPad();
            logControl= logPad.setAsStaticDisplay(true);
            //logPad.setText("\n\n\n");
            Dimension dev=Device.getScreenSize();
            logControl.setPreferredSize(dev.width,dev.height/8);
        }
    }
    
    /**
     * Return the display control to any form that wants to display the logger.
     * @return logControl reference.
     */
    public Control getLogControl() {
        //return logPad;
        if(!ISCONTROLENABLED) return null;
        return logControl;
    }
    
    /**
     * Log an exception to the log file.
     * @param ex Exception to log, with the stack trace.
     */
    public void addExceptionToLog(Exception exL) {
        if(ISFILEENABLED) {
            try {
                fLog.print("["+Vm.getTimeStamp()+"] "+exL);
                fLog.print(Vm.getAStackTrace(exL));
                fLog.flush();
            } catch (IOException ex) {
                (new MessageBox("Log error",Vm.getAStackTrace(ex),
                        MessageBox.MBOK)).execute();
                Vm.exit(0);
            }
        }
    }
    
    /**
     * Adds a string at the end of the log and displays the last line.
     * Also sleeps 1s if called in a Thread to allow the user to see the display.
     * @param msg Message to display. May contain '\n' characters.
     */
    public void addToLog(String msg) {
        if(ISFILEENABLED) {
            try {
                fLog.print("["+Vm.getTimeStamp()+"]"+msg);
                fLog.flush();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        if(ISCONTROLENABLED) {
            if(isFreezed) {
                stLogContent = stLogContent+msg;
            }else{
                String log=logPad.getText()+msg;
                logPad.setText(log);
            }
//        int nbL=countLines(log);
//        logPad.scrollTo(nbL,true);
//        if(mThread.inThread()) {
//            try {
//                mThread.sleep(300);
//            } catch (InterruptedException ex) {
//                // nothing
//            }
//        }
//        if(Gui.focusedControl()==logPad) {
//            Gui.takeFocus(null,ControlConstants.ByRequest);
//        }
            //logPad.repaint();
//        System.out.println(msg);
        }
    }
    
    /**
     * Set the log to the message, erasing previous content.
     * @param msg Message to display, may be multi-line using '\n' character.
     */
    public void setLog(String msg) {
        if(ISFILEENABLED) {
            try {
                fLog.print(msg);
                fLog.flush();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        if(ISCONTROLENABLED) {
            if(isFreezed) {
                stLogContent = stLogContent+msg;
            }else{
                logPad.setText(msg);
                int nbL=countLines(msg);
                logPad.scrollTo(nbL,true);
                if(mThread.inThread()) {
                    try {
                        mThread.sleep(300);
                    } catch (InterruptedException ex) {
                        // Nothing
                    }
                }
            }
        }
        //logPad.repaint();
//        System.out.println(msg);
    }
    
    /**
     * Freeze log refreshing to reduce 'real-time' disturbance.
     */
    public void freezeLog() {
        if(ISCONTROLENABLED) {
            isFreezed=true;
            stLogContent=logPad.getText();
        }
    }
    
    /**
     * Remove Freezed log refreshing to allow 'real-time' logging.
     */
    public void unFreezeLog() {
        if(ISCONTROLENABLED) {
            isFreezed=false;
            setLog(stLogContent);
        }
    }
    
    /**
     * Test log refreshing state.
     */
    public boolean isLogFreezed() {
        return(isFreezed);
    }
    
    /**
     * Count the number of '\n' in a string to know the number of lines.
     * Used to set the textpad at its last line.
     * @param st String where number of lines must be counted.
     * @return Number of lines in the string.
     */
    protected int countLines(String st) {
        int res=0;
        for( int idx=st.length()-1; idx>=0; idx--) {
            if( st.charAt(idx)=='\n' ) {
                res++;
            }
        }
        return res;
    }
}
